#ifndef __LICH_QOS_H
#define __LICH_QOS_H

#include "nodectl.h"
#include "lich_id.h"
#include "token_bucket.h"
#include "timepoint.h"

#define RECOVERY_TASK_MAX   (32)
#define RECOVERY_WAIT_THROT (1)

#define RECOVERY_QOS_IOPS_MIN     (20)
#define RECOVERY_QOS_STEP         (20)
#define RECOVERY_QOS_IOPS_DEFAULT (500)
#define RECOVERY_QOS_DIST         (500)
#define RECOVERY_QOS_EXP          (80)
#define RECOVERY_QOS_JITTER       (10)

typedef struct {
        int task_max;
        int wait_max;

        // int iops_min;
        // int iops_dft;
        // int iops_step;
        // int iops_dist;

        nodectl_option_t opt_iops_onoff;
        nodectl_option_t opt_iops_dft;
        nodectl_option_t opt_iops_min;
        nodectl_option_t opt_iops_step;
        nodectl_option_t opt_iops_dist;
        nodectl_option_t opt_iops_exp;
        nodectl_option_t opt_iops_jitter;
} qos_config_t;


int qos_config_init();

int qos_config_get_iops_onoff();
int qos_config_get_iops_dft();
int qos_config_get_iops_min();
int qos_config_get_iops_step();
int qos_config_get_iops_dist();
int qos_config_get_iops_exp();
int qos_config_get_iops_jitter();


typedef struct __qos_item_t {
        // co_cond_t cond;
        // uint64_t w1;
        // uint64_t w2;
        // uint64_t iops1;
        // uint64_t iops2;
        uint64_t enter_count;
        uint64_t request_count;
        uint64_t task_count;
        uint64_t exit_count;
        token_bucket_t bucket;
} qos_item_t;

typedef struct {
        uint64_t request;
        uint64_t token;
} qos_record_t;

typedef struct {
        struct timeval t;
        qos_record_t recovery;
        qos_record_t io;
        double dist;
} qos_point_t;

typedef struct {
        qos_point_t p1;
        qos_point_t p2;
} qos_range_t;

typedef struct __qos_t {
        int task_max;   ///< [16, 64?]
        int scale;      ///< [0, 100]
        int is_recovery;
        uint64_t recovery_count;

        qos_item_t io;
        qos_item_t recovery;

        qos_range_t range;
        timerange2_t io_range;
} qos_t;

struct __volume_proto;

/*from volume_proto_qos.c*/
int volume_proto_throt_request(struct __volume_proto *volume_proto, const char *name, size_t size);
int throt_request(struct __volume_proto *volume_proto, const char *name , size_t size);

int throt_qos_set(token_bucket_t *bucket, const char *_buf);
int throt_bw_set(token_bucket_t *bucket, const char *_buf);

int recovery_qos_init(qos_t *qos);

int volume_proto_recovery_throt_req(struct __volume_proto *volume_proto);

int volume_proto_recovery_enter(struct __volume_proto *volume_proto, const chkid_t *chkid);
int volume_proto_recovery_exit(struct __volume_proto *volume_proto, const chkid_t *chkid);

int volume_proto_io_enter(struct __volume_proto *volume_proto, const io_t *io);
int volume_proto_io_exit(struct __volume_proto *volume_proto);

#endif
